home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 2
/
Atari Mega Archive CD - Volume 2.iso
/
minix
/
up1510b.tgz
/
up1510b
/
src
/
commands
/
du.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-23
|
5KB
|
238 lines
/* du - report on disk usage Author: Alistair G. Crooks */
/*
* du.c 1.1 27/5/87 agc Joypace Ltd.
* 1.2 24 Mar 89 nick@nswitgould.oz
* 1.3 31 Mar 89 nick@nswitgould.oz
* 1.4 22 Feb 90 meulenbr@cst.prl.philips.nl
*
* Copyright 1987, Joypace Ltd., London UK. All rights reserved.
* This code may be freely distributed, provided that this notice
* remains attached.
*
* du - a public domain interpretation of du(1).
*
* 1.2: Fixed bug involving 14 character long filenames
* 1.3: Add [-l levels] option to restrict printing.
* 1.4: Added processing of multiple arguments
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <blocksize.h>
#include <stdio.h>
char *prog; /* program name */
char *optstr = "asl:"; /* -a and -s arguments */
int silent = 0; /* silent mode */
int all = 0; /* all directory entries mode */
char *startdir = "."; /* starting from here */
int levels = 255; /* # of directory levels to print */
#define LINELEN 256
#define DIRNAMELEN 14
#define LSTAT stat
typedef struct _dirstr {
ino_t inum;
char d_name[DIRNAMELEN];
} DIR;
DIR dir;
typedef struct _alstr {
int al_dev;
ino_t al_inum;
} ALREADY;
#define MAXALREADY 50
ALREADY already[MAXALREADY];
int alc = 0;
/*
* myindex - stop the scanf bug
*/
char *myindex(s, c)
register char *s;
register char c;
{
for (; *s; s++)
if (*s == c) return(s);
return(NULL);
}
/*
* getopt - parse the arguments given.
* retrieved from net.sources
*/
int opterr = 1;
int optind = 1;
int optopt;
char *optarg;
#define BADCH (int)'?'
#define EMSG ""
#define TELL(s) fputs(*nargv, stderr); fputs(s, stderr);\
fputc(optopt, stderr); fputc('\n', stderr);\
return(BADCH);
int getopt(nargc, nargv, ostr)
int nargc;
char **nargv;
char *ostr;
{
register char *oli;
static char *place = EMSG;
if (!*place) {
if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place)
return(EOF);
if (*place == '-') {
++optind;
return(EOF);
}
}
if ((optopt = (int) *place++) == (int) ':' || !(oli = myindex(ostr, optopt))) {
if (!*place) ++optind;
TELL(": illegal option -- ");
}
if (*++oli != ':') {
optarg = NULL;
if (!*place) ++optind;
} else {
if (*place)
optarg = place;
else if (nargc <= ++optind) {
place = EMSG;
TELL(": option requires an argument -- ");
} else
optarg = nargv[optind];
place = EMSG;
++optind;
}
return(optopt);
}
/*
* makedname - make the pathname from the directory name, and the
* directory entry, placing it in out. If this would overflow,
* return 0, otherwise 1.
*/
int makedname(d, f, out, outlen)
char *d;
char *f;
char *out;
int outlen;
{
char *cp;
int length;
/* Find length (1-14) of directory entry */
cp = f;
for (length = 0; *cp && (length < 14); ++cp) ++length;
if (strlen(d) + length + 2 > outlen) return(0);
for (cp = out; *d; *cp++ = *d++);
if (*(cp - 1) != '/') *cp++ = '/';
while (length--) *cp++ = *f++;
*cp = '\0';
return(1);
}
/*
* done - have we encountered (dev, inum) before? Returns 1 for yes,
* 0 for no, and remembers (dev, inum).
*/
int done(dev, inum)
int dev;
ino_t inum;
{
register ALREADY *ap;
register int i;
int ret = 0;
for (i = 0, ap = already; i < alc; ap++, i++)
if (ap->al_dev == dev && ap->al_inum == inum) {
ret = 1;
break;
}
if (alc < MAXALREADY) {
already[alc].al_dev = dev;
already[alc++].al_inum = inum;
}
return(ret);
}
/*
* dodir - process the directory d. Return the long size (in blocks)
* of d and its descendants.
*/
long dodir(d, thislev)
char *d;
int thislev;
{
struct stat s;
long total = 0L;
char dent[LINELEN];
int fd;
if ((fd = open(d, O_RDONLY)) < 0) return(0L);
while (read(fd, &dir, sizeof(dir)) > 0) {
if (strcmp(dir.d_name, ".") == 0 ||
strcmp(dir.d_name, "..") == 0)
continue;
if (dir.inum == 0) continue;
if (!makedname(d, dir.d_name, dent, sizeof(dent))) continue;
if (LSTAT(dent, &s) < 0) continue;
if (s.st_nlink > 1 && done(s.st_dev, s.st_ino)) continue;
if ((s.st_mode & S_IFMT) == S_IFDIR)
total += dodir(dent, thislev - 1);
switch (s.st_mode & S_IFMT) {
case S_IFREG:
case S_IFDIR:
total += (s.st_size + BLOCK_SIZE) / BLOCK_SIZE;
break;
}
if (all && (s.st_mode & S_IFMT) != S_IFDIR)
if (thislev > 0) /* this is correct - file in subdir */
printf("%ld\t%s\n",
(s.st_size + BLOCK_SIZE) / BLOCK_SIZE, dent);
}
close(fd);
if (!silent)
if (thislev >= 0) /* this is correct - subdir itself */
printf("%ld\t%s\n", total, d);
return(total);
}
/*
* OK, here goes...
*/
main(argc, argv)
int argc;
char **argv;
{
long tot;
int c;
prog = argv[0];
while ((c = getopt(argc, argv, optstr)) != EOF) switch (c) {
case 'a': all = 1; break;
case 's': silent = 1; break;
case 'l': levels = atoi(optarg); break;
default:
fprintf(stderr,
"Usage: %s [-a] [-s] [-l levels] [startdir]\n", prog);
exit(1);
}
do {
if (optind < argc) startdir = argv[optind++];
tot = dodir(startdir, levels);
if (silent) printf("%ld\t%s\n", tot, startdir);
} while (optind < argc);
exit(0);
}